package cn.cxyxj.code_auth_jwt_persistence_prod.config;

import cn.cxyxj.code_auth_jwt_persistence_prod.common.RedisKey;
import cn.cxyxj.code_auth_jwt_persistence_prod.entity.SysUser;
import cn.cxyxj.code_auth_jwt_persistence_prod.entity.SysUserDetails;
import cn.cxyxj.code_auth_jwt_persistence_prod.utils.RedisUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.stereotype.Component;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * 自定义 jwt token 信息
 */
// extends JwtAccessTokenConverter {
// implements TokenEnhancer {
public class CustomAdditionalInformation extends JwtAccessTokenConverter {

    // client_access_token:1:client_a:token
    private static final String ACCESS = "client_access_token:%s:%s:%s";
    private static final String REFRESH = "client_refresh_token:%s:%s:%s";
    private static final String CLIENT_TOKEN = "client_token:%s:%s";

    private static final String CLIENT_REFRESH_TOKEN = "client_refresh_token:%s:%s";

    private static final String CLIENT_ACCESS_TOKEN = "client_access_token:%s";

    /**
     * @param accessToken:Token           信息对象，可以往里面添加额外信息
     * @param authentication：OAuth2认证信息对象
     * @return
     */
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {

        Map<String, Object> additionalInformation = new LinkedHashMap<>();

        // 包含 /oauth/token接口的 OAuth2 请求信息
        OAuth2Request oAuth2Request = authentication.getOAuth2Request();
        String clientId = oAuth2Request.getClientId();
        if (StrUtil.isEmpty(clientId)) {
            // 直接登录认证中心
        } else {
            // 第三方登录
        }
        // 判断当前客户端是否内部应用，如果是，则在 Token 添加用户菜单、用户权限信息
        // 如果如需要当前登录用户信息，也可以从 SecurityContextHolder 中获取。
        SysUserDetails principal = (SysUserDetails) authentication.getUserAuthentication().getPrincipal();
        SysUser sysUser = principal.getSysUser();
        Set<String> urlSet = principal.getUrlSet();
        additionalInformation.put("urlSet", urlSet);


        additionalInformation.put("account", sysUser.getAccount());
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);

        OAuth2AccessToken enhance = super.enhance(accessToken, authentication);
        String value = enhance.getValue();
        String refreshToken = enhance.getRefreshToken().getValue();

        // 是否需要
        RedisUtil.set(String.format(RedisKey.RESOURCES_ACCESS_TOKEN, value), accessToken);

        //RedisUtil.set(String.format(RedisKey.ACCESS, sysUser.getAccount(), clientId, value), accessToken);
        RedisUtil.set(String.format(RedisKey.CLIENT_ACCESS_TOKEN, sysUser.getAccount(), clientId), value);

        //RedisUtil.set(String.format(RedisKey.REFRESH, sysUser.getAccount(), clientId, refreshToken), accessToken);
        RedisUtil.set(String.format(RedisKey.CLIENT_REFRESH_TOKEN, sysUser.getAccount(), clientId), value);

        // 记录该用户登录的客户端
        RedisUtil.lSet(String.format(RedisKey.USER_CLIENT, sysUser.getAccount()),clientId);
        return enhance;
    }

}